﻿#region Header

/*
Behavioral Rating of Dancing Human Crowds based on Motion Patterns
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using MathNet.Numerics.Interpolation.Algorithms;
using paravili.Services;
using Sebarf.Services.Interfaces;

#endregion

namespace paravili.Steps {
	/// <summary>
	/// Description of the class
	/// </summary>
	public class VisualizeMovementAtImage : ProcessStepWithMeasurement<IList<Cluster>> {
		#region Public Properties

		[ServiceRequest(IsOptional = true)]
		public IImageLocatorService ImageLocatorService { get; set; }

		[ConfigurabelStringValue(Name = "ImageProviderId")]
		public String ImageProviderId { get; set; }

		[ConfigurabelBooleanValue(Name = "IsEnable")]
		public bool IsEnable { get; set; }

		[ConfigurabelBooleanValue(Name = "Draw the number of the movement")]
		public bool DrawMovementNumber { get; set; }

		[ConfigurabelBooleanValue(Name = "Draw the hull of the clusters")]
		public bool DrawHull { get; set; }

		[ConfigurableLabValue(Name = "color of the hull")]
		public Lab HullColor { get; set; }

		[ConfigurableLabValue(Name = "color of the movement vector")]
		public Lab MovementColor { get; set; }

		[ConfigurableLabValue(Name = "color of the movement numbers")]
		public Lab MovementNumberColor { get; set; }

		[ConfigurabelBooleanValue(Name = "uses cubic splines to connect the points")]
		public bool UseCubigSplines { get; set; }

		#endregion

		#region Public Methods

		public VisualizeMovementAtImage() {
			ImageProviderId = "BgrToLabConverter.ImageData";
			IsEnable = true;
			HullColor = new Lab(200, 60, 255);
			MovementColor = new Lab(200, 16, 16);
			MovementNumberColor = new Lab(200, 200, 200);
			UseCubigSplines = false;
		}

		protected override IList<Cluster> OnProcess(IList<Cluster> toProcess) {
			if (toProcess == null) {
				return toProcess;
			}
			if (IsEnable && ImageLocatorService != null) {
				Image<Lab, byte> img = ImageLocatorService.GetImage(ImageProviderId);
				if (img != null) {
					var font = new MCvFont(FONT.CV_FONT_HERSHEY_PLAIN, 1.2, 1.2);
					int index = 0;

					foreach (Cluster cluster in toProcess) {
						var points = new List<Point>();
						Cluster c = cluster;
						do {
							points.Add(new Point((int)c.AverageXValue, (int)c.AverageYValue));
							c = c.PreviousCluster;
						} while (c != null);
						if (points.Count < 2) {
							continue;
						}
						if (UseCubigSplines) {
							var t = new double[points.Count];
							for (int i = 0; i < t.Length; i++) {
								t[i] = i;
							}
							var splineX = new CubicSplineInterpolation();
							splineX.Init(t, points.Select(x => (double)x.X).ToArray());
							var splineY = new CubicSplineInterpolation();
							splineY.Init(t, points.Select(x => (double)x.Y).ToArray());

							points.Clear();
							for (double i = 0; i < t.Length; i += 0.2) {
								points.Add(new Point((int)splineX.Interpolate(i), (int)splineY.Interpolate(i)));
							}
						}
						img.DrawPolyline(points.ToArray(), false, MovementColor, 3);
						img.Draw(new CircleF(new PointF((float)cluster.AverageXValue, (float)cluster.AverageYValue), 4),
								  MovementColor, 4);
						if (DrawMovementNumber) {
							img.Draw(index.ToString(), ref font, points[0], MovementNumberColor);
						}
						if (DrawHull) {
							img.Draw(
								new Rectangle(cluster.Min, new Size((cluster.Max.X - cluster.Min.X), (cluster.Max.Y - cluster.Min.Y))),
								HullColor, 2);
						}
						index++;
					}
				}
			}

			return toProcess;
		}

		#endregion
	}
}